// ignore_for_file: always_specify_types

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_project/tool/utils/dz_logger.dart';

import 'code/http_api.dart';
import 'code/http_config.dart';
import 'code/http_engine.dart';
import 'code/http_result.dart';

class HttpManager {
  factory HttpManager() {
    return _shared;
  }

  HttpManager._internal();
  static const List<int> _validateCodes = <int>[200, 401, 422, 429];
  static final HttpManager _shared = HttpManager._internal();
  static void setConfig(HttpConfig config) {
    HttpManager()._config = config;
  }

  final NetworkEngine _httpEngine = NetworkEngine();

  HttpConfig? _config;

  Future<HttpResult> request(HttpApi api,
      {Map<String, String>? filePaths, CancelToken? cancelToken}) async {
    String path = api.path();
    if (api.method == Method.get) {
      api.params().forEach((String key, value) {
        if (path.contains(key)) {
          path = path.replaceAll(":$key", value.toString());
        }
      });
    }
    Map<String, dynamic> headers = {};
    if (_config?.headers() != null) {
      Map<String, dynamic> configHeaders = _config?.headers() ?? {};
      headers.addAll(configHeaders);
    }
    if (api.header != null) {
      Map<String, dynamic> apiHeaders = api.header ?? {};
      headers.addAll(apiHeaders);
    }

    ResponseType responseType = ResponseType.json;
    if (api.responseType == HttpResponseType.bytes) {
      responseType = ResponseType.bytes;
    } else if (api.responseType == HttpResponseType.plain) {
      responseType = ResponseType.plain;
    } else if (api.responseType == HttpResponseType.stream) {
      responseType = ResponseType.stream;
    }
    final String baseUrl = api.baseUrl ?? _config?.baseUrl() ?? "";
    const List<int> validateCodes = _validateCodes;
    final BaseOptions options = BaseOptions(
      baseUrl: baseUrl,
      connectTimeout: _config?.timeout,
      sendTimeout: _config?.timeout,
      receiveTimeout: _config?.timeout,
      responseType: responseType,
      headers: headers.isEmpty ? null : headers,
      validateStatus: (int? status) => validateCodes.contains(status),
    );
    _httpEngine.setOptions(options);

    try {
      Response response;
      if (!kReleaseMode) {
        final DateTime startTime = DateTime.now();
        if (api.method == Method.get) {
          response = await _httpEngine.executeGet(
              path: api.path(), params: api.params());
        } else {
          response = await _httpEngine.executePost(
              path: api.path(), params: api.params(), paths: filePaths);
        }
        final DateTime endTime = DateTime.now();
        final int duration = endTime.difference(startTime).inMilliseconds;
        DZLog.d(
            '网络请求耗时 $duration 毫秒,HttpCode:${response.statusCode} HttpMessage:${response.statusMessage} 响应内容 ${response.data}}');
      } else {
        if (api.method == Method.get) {
          response = await _httpEngine.executeGet(
              path: api.path(), params: api.params());
        } else {
          response = await _httpEngine.executePost(
              path: api.path(), params: api.params(), paths: filePaths);
        }
        // Log.logRelease("请求参数-${api.params()}");
      }
      if (validateCodes.contains(response.statusCode)) {
        DZLog.d("请求成功-${response.data}");
        return HttpResult(isSuccess: true, dataJson: response.data, code: 200);
      } else {
        return HttpResult(isSuccess: false);
      }
    } on DioException catch (e) {
      DZLog.d(
          tag: "[HttpManager]",
          "DioException：$e  其他错误Error:${e.error.toString()}");
      if (e.response != null) {
        // 如果其他的Http网络请求的Code的处理
        DZLog.d("网络请求错误，data：${e.response?.data}");
        return HttpResult(
            isSuccess: false,
            errorMsg:
                "错误码：${e.response?.statusCode} 错误信息：${e.response?.statusMessage}");
      } else if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.sendTimeout ||
          e.type == DioExceptionType.receiveTimeout) {
        return HttpResult(isSuccess: false, errorMsg: "网络连接超时，请稍后再试");
      } else if (e.type == DioExceptionType.cancel) {
        return HttpResult(isSuccess: false, errorMsg: "网络请求已取消");
      } else if (e.type == DioExceptionType.badCertificate) {
        return HttpResult(isSuccess: false, errorMsg: "网络连接证书无效");
      } else if (e.type == DioExceptionType.badResponse) {
        return HttpResult(isSuccess: false, errorMsg: "网络响应错误，请稍后再试");
      } else if (e.type == DioExceptionType.connectionError) {
        return HttpResult(isSuccess: false, errorMsg: "网络连接错误，请检查网络连接");
      } else if (e.type == DioExceptionType.unknown) {
        //未知错误中尝试打印具体的错误信息
        if (e.error != null) {
          if (e.error.toString().contains("HandshakeException")) {
            return HttpResult(isSuccess: false, errorMsg: "网络连接错误，请检查网络连接");
          } else {
            return HttpResult(
                isSuccess: false,
                errorMsg: e.error.toString()); //这里打印的就是英文错误了，没有格式化
          }
        } else {
          return HttpResult(isSuccess: false, errorMsg: "网络请求出现未知错误");
        }
      } else {
        //如果有response走Api错误
        return HttpResult(isSuccess: false, errorMsg: e.message);
      }
    }
  }
}
